const express = require("express");
const router = express.Router();

const { Category } = require("../../models");
const { Op } = require("sequelize");

const { NotFoundError, success, failure } = require("../../utils/response");

router.get("/", async function (req, res) {
  try {
    // query
    const query = req.query;
    // 分页
    // 当前页面
    const currentPage = Math.abs(Number(query.currentPage)) || 1; // 默认第一页
    const pageSize = Math.abs(Number(query.pageSize)) || 10; // 默认每页10条数据

    /**
     * select * from 表名 LIMIT offset, limit;
     * ==> 从offset开始，获取limit条数据
     * ==> 相当于 select * from 表名 LIMIT offset, pagesize;
     * ==> 相当于 select * from 表名 LIMIT (currentPage - 1) * pageSize, pagesize;
     */
    const offset = (currentPage - 1) * pageSize;

    // 分类倒序排列
    const condition = {
      order: [["id", "desc"]],
      limit: pageSize,
      offset,
    };

    // 标题模糊搜索
    // 用户传递了name查询
    /**
     * SELECT * FROM 表明 Where name like %标题 10%
     * 以上语句，将匹配name字段值中 xxx标题 10xxx的内容，例子中就是【分类标题 10】和【分类标题 100】两篇
     * 如果是
     * SELECT * FROM 表明 Where name like %标题 10
     * 则只匹配【分类标题 10】，不会匹配【分类标题 100】
     *
     *
     * 所以，like是模糊查询
     * % 表示匹配内容，类似于占位符的作用
     */
    if (query.name) {
      condition.where = {
        name: {
          [Op.like]: `%${query.name}%`,
        },
      };
    }

    // 查找分类数据
    /**
     * findAndCountAll,返回{count, rows}
     * count: 总条数,
     * rows: 数据
     */
    const { count, rows } = await Category.findAndCountAll(condition);

    success(res, "查询分类列表成功", {
      categories: rows,
      pagination: {
        currentPage,
        total: count,
        pageSize,
      },
    });
  } catch (err) {
    failure(res, err);
  }
});

// 分类象详情
router.get("/:id", async function (req, res) {
  try {
    // findByPk, 通过主键查找，primary key 【pk】
    const category = await getCategory(req);
    success(res, "查询分类成功", { category });
  } catch (err) {
    failure(res, err);
  }
});

// 创建分类
router.post("/", async function (req, res) {
  try {
    // 白名单过滤，避免用户提交id等数据,只保留需要的数据
    const body = filterBody(req);
    const category = await Category.create(body);
    // 201，表示请求成功，且创建了数据
    success(res, "分类创建成功", category, 201);
  } catch (error) {
    failure(res, error);
  }
});

/*
    删除分类
*/
router.delete("/:id", async function (req, res) {
  try {
    const category = await getCategory(req);
    await category.destroy();
    success(res, "删除分类成功");
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 更新分类
 */
router.put("/:id", async function (req, res) {
  try {
    const category = await getCategory(req);

    await category.update(filterBody(req));
    success(res, "分类更新成功", category);
  } catch (error) {
    failure(res, error);
  }
});

/**
 * 公共方法：白名单过滤
 * @param {*} req 
 * @returns 
 */
function filterBody(req) {
  return {
    name: req.body.name,
    rank: req.body.rank,
  };
}

// 公共方法，查找分类
async function getCategory(req) {
  const category = await Category.findByPk(req.params.id);

  if (!category) {
    // 抛出异常，让trycatch捕获
    throw new NotFoundError(`ID:(${req.params.id}) 分类未找到`);
  }

  return category;
}

module.exports = router;
